home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
vol_100
/
198_02
/
menu.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-01-21
|
12KB
|
520 lines
/* Menu: Menu processor
*/
#include <stdio.h>
#include "estruct.h"
#include "edef.h"
#if MENUS
/* screen area (taken from display.c, should be moved to a header file) */
typedef struct VIDEOTAG {
int v_flag; /* Flags */
#if COLOR
int v_fcolor; /* current forground color */
int v_bcolor; /* current background color */
int v_rfcolor; /* requested forground color */
int v_rbcolor; /* requested background color */
#endif
char v_text[1]; /* Screen data. */
} VIDEO;
#define VFCHG 0x0001 /* Changed flag */
#define VFEXT 0x0002 /* extended (beyond column 80) */
#define VFREV 0x0004 /* reverse video status */
#define VFREQ 0x0008 /* reverse video request */
#define VFCOL 0x0010 /* color change requested */
extern VIDEO **vscreen; /* Virtual screen. */
/* menu codes return by getmkey() */
#define MENUMERR 0 /* unrecognized command */
#define MENUMUP 1 /* go up */
#define MENUMDOWN 2 /* go down */
#define MENUMLEFT 3 /* go left */
#define MENUMRIGHT 4 /* go right */
#define MENUMENTER 5 /* CR */
/* box drawing characters */
#if IBMPC
#define BOXUR 218
#define BOXUL 191
#define BOXLR 192
#define BOXLL 217
#define BOXH 196
#define BOXV 179
#else
#define BOXUR '.'
#define BOXUL '.'
#define BOXLR '\''
#define BOXLL '\''
#define BOXH '-'
#define BOXV '|'
#endif
extern int fileread(), filesave(), filewrite(), insfile();
extern int spawncli(), spawn(), quit();
extern int forwsearch(), forwhunt(), nullproc(), sreplace();
extern int forwline(), backline(), forwchar(), backchar();
extern int newline(), openline(), indent(), tab(), insspace();
#if DECEDT
extern int scupwind(), scdnwind();
#endif
#define FPNULL 0
typedef struct {
char *m_text;
int m_up;
int m_down;
int m_left;
int m_right;
int (*m_func)();
} MENUTABLE;
MENUTABLE menudata[] = {
/* 0 */ { "", 0, 1, 0, 0, FPNULL },
/* 1 */ { "File", 0, 2, 0, 9, FPNULL }, /* File option */
/* 2 */ { "New", 1, 0, 0, 3, fileread }, /* create new file */
/* 3 */ { "Open", 1, 0, 2, 4, fileread }, /* read old file */
/* 4 */ { "Insert", 1, 0, 3, 5, insfile }, /* insert file */
/* 5 */ { "Save", 1, 0, 4, 6, filesave }, /* save current file */
/* 6 */ { "save As", 1, 0, 5, 7, filewrite }, /* write a file */
/* 7 */ { "Dos", 1, 0, 6, 8, spawncli }, /* do a DOS command */
/* 8 */ { "Exit", 1, 0, 7, 0, quit }, /* exit */
/* 9 */ { "Edit", 0, 10, 1, 13, FPNULL },
/* 10 */ { "Search", 9, 0, 0, 11, forwsearch }, /* search */
/* 11 */ { "Last search", 9, 0, 10, 12, forwhunt }, /* hunt */
/* 12 */ { "Replace", 9, 0, 11, 0, sreplace }, /* replace */
/* 13 */ { "Compile", 0, 0, 9, 0, spawn }
};
int menutwid; /* width of entries on top line */
int menulast; /* last option on main menu */
menuinit() /* create menu line */
{
LINE *lalloc();
int i, j, num, wid, m, len;
if (menuflag) {
menulast = 1;
if (menuline != NULL) free(menuline);
menuline = lalloc(term.t_ncol);
if (menuline == NULL) {
mlwrite("[Can not create menu line]");
menuflag = 0;
return;
}
menuline->l_fp = NULL;
menuline->l_bp = NULL;
menuline->l_used = term.t_ncol;
num = menucount(0);
menutwid = llength(menuline) / num;
wid = menutwid - 1;
for (i = 0; i < llength(menuline); i++)
lputc(menuline, i, ' ');
j = 0;
for (m = 1; m != 0; m = menudata[m].m_right) {
for (i = 0; menudata[m].m_text[i] && i < wid; i++)
lputc(menuline, i+j, menudata[m].m_text[i]);
j += menutwid;
}
}
}
/* find number of options beneath m */
int menucount(m)
int m;
{
int c;
c = 0;
for(m = menudata[m].m_down; m != 0; m = menudata[m].m_right)
c++;
return(c);
}
/* find length of longest string under m */
int menulen(m)
int m;
{
int i, len;
len = 0;
for(m = menudata[m].m_down; m != 0; m = menudata[m].m_right) {
i = strlen( menudata[m].m_text );
if (i > len) len = i;
}
return(len);
}
int menukey; /* current key pressed */
getmkey() /* read a menu movement command */
{
int c, cmd;
int (*f)(), (*getbind())();
#if C86
int (*fbackline)(), (*fforwline)();
int (*fbackchar)(), (*fforwchar)(), (*findent)(), (*ftab)();
int (*finsspace)(), (*fnewline)(), (*fopenline)();
#if DECEDT
int (*fscupwind)(), (*fscdnwind)();
fscupwind = scupwind;
fscdnwind = scdnwind;
#endif
fbackline = backline;
fforwline = forwline;
fbackchar = backchar;
fforwchar = forwchar;
findent = indent;
ftab = tab;
finsspace = insspace;
fnewline = newline;
fopenline = openline;
#else
#if DECEDT
#define fscupwind scupwind
#define fscdnwind scdnwind
#endif
#define fbackline backline
#define fforwline forwline
#define fbackchar backchar
#define fforwchar forwchar
#define findent indent
#define ftab tab
#define finsspace insspace
#define fnewline newline
#define fopenline openline
#endif
TTflush();
c = getcmd();
menukey = c & 0x7F;
if (menukey >= 'a' && menukey <= 'z') menukey += 'A' - 'a';
f = getbind(c);
if (f == fbackline) cmd = MENUMUP;
else if (f == fforwline) cmd = MENUMDOWN;
#if DECEDT
else if (f == fscupwind) cmd = MENUMUP;
else if (f == fscdnwind) cmd = MENUMDOWN;
#endif
else if (f == fbackchar) cmd = MENUMLEFT;
else if (f == fforwchar || f == findent || f == ftab ||
f == finsspace) cmd = MENUMRIGHT;
else if (f == fnewline || f == fopenline) cmd = MENUMENTER;
else if (c == ' ') cmd = MENUMRIGHT;
else if (c == '\n') cmd = MENUMENTER;
else cmd = MENUMERR;
return(cmd);
}
int menumatch(m) /* check if menukey is in menu item m */
int m;
{
char *cp;
if (menukey >= 'A' && menukey <= 'Z')
for(cp = menudata[m].m_text; *cp != '\0'; cp++)
if (*cp == menukey) return(1);
return(0);
}
menudo(r, c, m) /* execute a menu enter command */
int r, c, m;
{
int status;
status = HOOK;
if (menudata[m].m_down != 0)
status = menupull(r, c, m);
if (menudata[m].m_func != FPNULL)
status = (*menudata[m].m_func)(FALSE, 1);
return(status);
}
menuput(row, col, len, normal) /* display a string */
int row, col, len, normal;
{
char *str;
str = &(vscreen[row]->v_text[col]);
if (row > 0) normal = 1 - normal;
TTrev(normal);
movecursor(row, col);
if (normal) {
#if COLOR
TTforg(gbcolor);
TTbacg(gfcolor);
#endif
#if IBMPC
menuwrite(row, col, str, len, gbcolor, gfcolor);
#endif
}
else {
#if COLOR
TTforg(gfcolor);
TTbacg(gbcolor);
#endif
#if IBMPC
menuwrite(row, col, str, len, gfcolor, gbcolor);
#endif
}
ttcol += len;
#if IBMPC
#else
while(len-- > 0) TTputc(*str++);
TTrev(0);
#endif
}
int menupull(row, col, men) /* pull down a menu */
int row, col, men;
{
int nrows, ncols;
int c, r, m, curmrow, status, tmprow, tmpm;
char *save, *sp, *tp;
register VIDEO *vp;
/* initialize */
++row;
nrows = menucount(men) + 2;
if (nrows > term.t_nrow) nrows = term.t_nrow;
if (row + nrows > term.t_nrow) row = term.t_nrow - nrows;
ncols = menulen(men) + 2;
if (ncols > term.t_ncol) ncols = term.t_ncol;
if (col + ncols > term.t_ncol) col = term.t_ncol - ncols;
save = malloc(nrows * ncols);
status = HOOK;
if (save == NULL) {
mlwrite("[No memory to pull down menu]");
return(status);
}
/* pull down the menu */
m = menudata[men].m_down;
sp = save;
for(r = row; r < row + nrows; r++) {
/* save old line */
tp = &(vscreen[r]->v_text[col]);
for(c = 0; c < ncols; c++) *sp++ = *tp++;
/* create new line */
tp = &(vscreen[r]->v_text[col]);
if (r == row) {
*tp++ = BOXUR;
for(c = 0; c < ncols-2; c++) *tp++ = BOXH;
*tp = BOXUL;
}
else if (r == row + nrows - 1) {
*tp++ = BOXLR;
for(c = 0; c < ncols-2; c++) *tp++ = BOXH;
*tp = BOXLL;
}
else {
*tp++ = BOXV;
for(c = 0; c < ncols-2 && menudata[m].m_text[c]; c++)
*tp++ = menudata[m].m_text[c];
for(; c < ncols-2; c++)
*tp++ = ' ';
*tp = BOXV;
m = menudata[m].m_right;
}
/* display new line */
menuput(r, col, nc